package gateway.mgt

import com.amihaiemil.camel.Yaml
import gateway.mgt.api.ApiDefinition
import gateway.mgt.api.ApiGroup
import gateway.mgt.api.ApiInOutParam
import grails.testing.gorm.DomainUnitTest
import spock.lang.Specification

class ApiInOutParamSpec extends Specification implements DomainUnitTest<ApiInOutParam> {

    static final ApiGroup apiGroupInstance = new ApiGroup(name: "default")

    static final ApiDefinitionProperties = [
            apiGroup: apiGroupInstance, name: "demo1", description: "demo api 1",
            request : [path: "/Service-Set-1/sampleApi1"], backend: [host: "lb://Service-Set-1", path: "/sampleApi1"]
    ]

    static final ApiDefinition apiDefinitionInstance = new ApiDefinition(ApiDefinitionProperties)

    static final ValidPropertiesSet = [
            [
                    apiDefinition: apiDefinitionInstance, order: 1, description: "a demo inout parameter1",
                    type         : ApiInOutParam.Type.String, defaultValue: "Hello world",
                    atRequest    : [scope: ApiInOutParam.Scope.Query, name: "ip1"],
                    atBackend    : [scope: ApiInOutParam.Scope.Header, name: "op1"]
            ],
            [
                    apiDefinition: apiDefinitionInstance, order: 2, description: "Transfer a inout parameter2",
                    type         : ApiInOutParam.Type.Integer,
                    atRequest    : [scope: ApiInOutParam.Scope.Query, name: "ip2"],
                    atBackend    : [scope: ApiInOutParam.Scope.Path, name: "op2"]
            ],
            [
                    apiDefinition: apiDefinitionInstance, order: 2, description: "Remove a request parameter",
                    type         : ApiInOutParam.Type.Integer,
                    atRequest    : [scope: ApiInOutParam.Scope.Header, name: "ip2"],
                    atBackend    : null
            ]
    ]

    static final InvalidPropertiesSet = [
            [
                    order                 : 1, type: ApiInOutParam.Type.String,
                    atRequest             : [scope: ApiInOutParam.Scope.Query],
                    atBackend             : [name: "op1"],
                    expected_error_counter: 3
            ],
            [
                    apiDefinition         : apiDefinitionInstance, order: -2, type: ApiInOutParam.Type.Integer,
                    atRequest             : null,
                    atBackend             : [scope: ApiInOutParam.Scope.Path, name: "op2"],
                    expected_error_counter: 2
            ],
            [
                    apiDefinition         : apiDefinitionInstance, order: 1, type: ApiInOutParam.Type.String,
                    atRequest             : [scope: ApiInOutParam.Scope.Query], defaultValue: "abc",
                    expected_error_counter: 2
            ]
    ]

    def setupSpec() {
        apiGroupInstance.save(flush: true)
        apiDefinitionInstance.save(flush: true)
    }

    def setup() {
    }

    def cleanup() {
    }

    void "test a valid properties"() {
        given:
        def instance = new ApiInOutParam(params)

        when:
        instance.save(flush: true)

        then:
        !instance.hasErrors()

        where:
        params << ValidPropertiesSet
    }

    void "test an invalid properties"() {
        given:
        def instance = new ApiInOutParam(params)

        when:
        instance.save(flush: true)

        then:
        instance.hasErrors()

        and:
        instance.errors.allErrors.size() == params.expected_error_counter

        where:
        params << InvalidPropertiesSet
    }

    void "test method: 'Pluggable#plug(Map)' of the instance for 'remove a request parameter'"() {
        given:
        def params = [
                apiDefinition: apiDefinitionInstance, order: 2, description: "Remove a request parameter",
                type         : ApiInOutParam.Type.Integer,
                atRequest    : [scope: ApiInOutParam.Scope.Header, name: "ip2"],
                atBackend    : null
        ]
        def paramsBuilder = [filters: Yaml.createYamlSequenceBuilder(), predicates: Yaml.createYamlSequenceBuilder()]

        when:
        new ApiInOutParam(params).save(flush: true).plug(paramsBuilder)

        and:
        def parts = paramsBuilder.filters.build().toString().split("=")

        then:
        parts.size() == 2
        parts[0] == "- RemoveRequestHeader"
        parts[1] == params.atRequest.name
    }
}
